<script setup>
import {onMounted, onUnmounted, ref, watch} from "vue";

const props = defineProps({
  items: {
    type: Array,
    required: true,
  },
  data: {
    type: Object,
    default: () => {
      return {};
    }
  }
});

const show = ref(false);
const x = ref(0);
const y = ref(0);
// 是从哪个数据出发的右键菜单，方便获取到数据，进行后续的回调处理
const callbackData = ref(props.data);

// 监听一下点击菜单时候的数据
watch(() => props.data, (newValue, oldValue) => {
  callbackData.value = newValue;
}, {deep: true});

// 点击某个菜单项的回调函数
const handleClick = (item) => {
  if (item.action) {
    // 回调函数
    item.action(callbackData?.value);
  }
  // 隐藏菜单
  show.value = false;
};

const open = (event) => {
  // 组长事件的默认行为，也就是阻止弹出浏览器默认的右键菜单
  event.preventDefault();
  // 显示自定义的右键菜单
  show.value = true;
  // 设置一下菜单显示的位置
  x.value = event.clientX;
  y.value = event.clientY;
};

// 监听全局点击事件，方便隐藏菜单
const hideMenu = (event) => {
  // 如果点击的位置不在菜单内部，则隐藏上下文菜单
  if (!event.target.closest('.v-contextmenu-container')) {
    show.value = false;
  }
};

onMounted(() => {
  // 组件挂载时添加事件监听器
  document.addEventListener('click', hideMenu);
});

onUnmounted(() => {
  // 组件卸载时移除事件监听器
  document.removeEventListener('click', hideMenu);
});

// 对外暴露 open 方法
defineExpose({
  open,
});
</script>

<template>
  <div class="v-contextmenu-container" v-if="show" :style="{ top: `${y}px`, left: `${x}px` }">
    <div class="v-contextmenu-item" v-for="(item, index) in items" :key="index"
         @click="handleClick(item)">
      {{ item.label }}
    </div>
  </div>
</template>

<style scoped>
.v-contextmenu-container {
  position: fixed;
  background: white;
  border: 1px solid #CCCCCC;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border-radius: 4px;
  padding: 8px 10px;
  z-index: 2000;
}

.v-contextmenu-item {
  font-size: 14px;
  cursor: pointer;
  padding: 8px 16px;
  margin: 4px 0;
  border-radius: 4px;
}

.v-contextmenu-item:hover {
  background-color: #F1F1F4;
}
</style>